#include "ObjectElement.h"

namespace OpenNano
{
    REGISTER_OBJECT_FACTORY( ObjectElement, OBJECT_TAG );

    ObjectElement::ObjectElement( TiXmlElement * element) :
                    ConfigElement(element), logger(log4cplus::Logger::getInstance( OBJECT_TAG )),
                    _name(), _properties(), _everything_is_good_so_far(true)
                {
                }

    ObjectElement::~ObjectElement()
    {
        _properties.clear();
    }

    void ObjectElement::init()
    {
        LOG4CPLUS_INFO(logger, "Object element: initialized");
    }

    const std::string& ObjectElement::getName() const
    {
        return _name;
    }

    const PropertyMap& ObjectElement::getProperties() const
    {
        return _properties;
    }

    bool ObjectElement::getProperty(const std::string& name, std::string &value)
    {
        bool property_found = false;
        PropertyMap::iterator it = _properties.find(name);
        if ( it != _properties.end() )
        {
            value = it->second;
            property_found=true;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Property not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return property_found;

    }

    void ObjectElement::attributeFound(TiXmlAttribute * attribute)
    {
        if ( attribute->NameTStr().compare(OBJECT_NAME_ATTRIBUTE) == 0 )
        {
            _name=attribute->ValueStr();
        }
        else
        {
            //attribute not recognized
            LOG4CPLUS_WARN(logger, "Attribute not recognized:");
            LOG4CPLUS_WARN(logger, attribute->NameTStr());

            unknownAttributeFound(attribute);
            _everything_is_good_so_far=false;
        }
    }

    void ObjectElement::childElementFound(TiXmlElement * childElement)
    {
        if ( childElement->ValueStr().compare(OBJECT_PROPERTY_ELEMENT) == 0 )
        {
            TiXmlAttribute * param = childElement->FirstAttribute();
            if ( param && param->NameTStr().compare(OBJECT_PROP_NAME_ATTRIB) == 0 &&
                        param->Next() && param->Next()->NameTStr().compare(OBJECT_PROP_VALUE_ATTRIB) == 0 )
            {
                //NOTE_TO_SELF:
                //if there are two property element with the same name
                //in the map there will be only one entry, with the value defined
                //in the last parsed element.
                _properties[ param->ValueStr() ] = param->Next()->ValueStr();
            }
            else
            {
                LOG4CPLUS_WARN(logger, "Name attribute of the option element not found/invalid");
                //parameter attribute not found/recognized
                _everything_is_good_so_far=false;
            }
        }
        else
        {
            //Element not recognized
            LOG4CPLUS_WARN(logger, "Child element not recognized:");
            LOG4CPLUS_WARN(logger, childElement->ValueStr());

            unknownElementFound(childElement);
            _everything_is_good_so_far=false;
        }
    }

    void ObjectElement::textFound(const char* text)
    {
        LOG4CPLUS_WARN(logger, "Text not recognized:");
        LOG4CPLUS_WARN(logger, text);

        unknownTextFound(text);
    }

    bool ObjectElement::postConfiguration()
    {
        return (!_name.empty()) && _everything_is_good_so_far;
    }



}
